package ch.ricosoft.hr;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URL;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import ch.ricosoft.hr.sorter.HomeLossPointSorter;
import ch.ricosoft.hr.sorter.HomePointSorter;
import ch.ricosoft.hr.sorter.InfoSorter;
import ch.ricosoft.hr.sorter.OutwardLossPointSorter;
import ch.ricosoft.hr.sorter.OutwardPointSorter;
import ch.ricosoft.hr.sorter.TotalLossPointSorter;
import ch.ricosoft.hr.sorter.TotalPointSorter;

public class ResultParser {
	private HashMap<String, Team> teamStatistics = new HashMap<String, Team>();

	private final static Logger LOG = Logger.getLogger(ResultParser.class
			.getName());

	public void parse(Date from, Date to, String group, String saison,
			PrintStream ps) throws IOException {

		SimpleDateFormat df = new SimpleDateFormat("dd.MM.yyyy");

		StringBuilder sb = new StringBuilder();
		sb.append("http://vvs.handball.ch/content.asp?");

		sb.append("datumvon=");
		sb.append(df.format(from));
		sb.append("&datumbis=");
		sb.append(df.format(to));
		sb.append("&verband=shv&include=resultate&res=resultat&filter=gruppe&zsaison=");
		sb.append(saison);
		sb.append("&isportal=1&lanId=1&gruppe=");
		sb.append(group);

		final String fullUrl = sb.toString();
		LOG.info(MessageFormat.format("Calling URL {0}", fullUrl));

		URL url = new URL(fullUrl);
		BufferedReader reader = new BufferedReader(new InputStreamReader(
				url.openStream()));

		StringWriter sw = new StringWriter();
		String line = reader.readLine();
		while (line != null) {
			sw.write(line);
			sw.write("\n");

			line = reader.readLine();
		}

		String responseBody = sw.toString();

		int beginBody = responseBody.toLowerCase().indexOf("<body");
		int endBody = responseBody.indexOf(">", responseBody.toLowerCase()
				.indexOf("</body"));

		responseBody = responseBody.substring(beginBody, endBody + 1);

		// remove scripts as they are not correctly formatted
		int index = 0;
		index = responseBody.indexOf("<table",
				responseBody.indexOf("<table") + 1);
		if (index >= 0) {
			int endIndex = responseBody.lastIndexOf("</table",
					responseBody.lastIndexOf("</table") - 1);
			if (endIndex >= 0) {
				endIndex = responseBody.indexOf(">", endIndex);

				responseBody = responseBody.substring(index, endIndex + 1);
			}
		}

		// remove images as they are not correctly formatted
		index = 0;

		while (index >= 0) {
			index = responseBody.indexOf("<img");
			if (index >= 0) {
				int endIndex = responseBody.indexOf(">", index);
				if (endIndex >= 0) {
					responseBody = responseBody.substring(0, index)
							+ responseBody.substring(endIndex + 1);
				}
			}
		}

		responseBody = responseBody.replaceAll("&nbsp;", " ");

		responseBody = responseBody.replaceAll("nowrap", "nowrap=\"\"");

		LOG.fine(MessageFormat.format("Extracted body: {0}", responseBody));

		SAXBuilder saxb = new SAXBuilder(false);
		try {
			Document doc = saxb.build(new StringReader(responseBody));

			// rush through
			teamStatistics.clear();
			Iterator<?> childIt = ((List<?>) doc.getRootElement().getChildren())
					.iterator();

			while (childIt.hasNext()) {
				Element child = (Element) childIt.next();
				if (child.getChildren().size() < 9) {
				} else {
					Element homeTeam = (Element) child.getChildren().get(3);
					String homeTeamS;
					if (homeTeam.getChildren().size() > 0) {
						homeTeamS = ((Element) homeTeam.getChildren().get(0))
								.getText().trim();
					} else {
						homeTeamS = homeTeam.getText().trim();
					}
					Element guestTeam = (Element) child.getChildren().get(4);
					String guestTeamS;
					if (guestTeam.getChildren().size() > 0) {
						guestTeamS = ((Element) guestTeam.getChildren().get(0))
								.getText().trim();
					} else {
						guestTeamS = guestTeam.getText().trim();
					}

					int res1 = Integer.parseInt(((Element) child.getChildren()
							.get(5)).getText());
					int res2 = Integer.parseInt(((Element) child.getChildren()
							.get(7)).getText());

					LOG.info(MessageFormat.format(
							"Found match between {0} and {1}, result {2}:{3}",
							homeTeamS, guestTeamS, res1, res2));

					Team t = teamStatistics.get(homeTeamS);
					if (t == null) {
						t = new Team(homeTeamS);
						teamStatistics.put(homeTeamS, t);
					}
					t.addHome(res1, res2);

					t = teamStatistics.get(guestTeamS);
					if (t == null) {
						t = new Team(guestTeamS);
						teamStatistics.put(guestTeamS, t);
					}
					t.addOutward(res2, res1);
				}
			}

			ArrayList<Team> teams = new ArrayList<Team>(teamStatistics.values());

			ps.println("<html><head><title>Komplett-Tabelle</title>"
					+ "<link rel=\"stylesheet\" href=\"/table.css\" /></head><body>");

			ps.println("<div id=\"total\">");
			createHtmlTable(teams, "Total: Punkte", new TotalPointSorter(), ps,
					"totp");
			createHtmlTable(teams, "Total: Verlustpunkte",
					new TotalLossPointSorter(), ps, "totvp");
			ps.println("</div>");

			ps.println("<div id=\"home\">");
			createHtmlTable(teams, "Heim: Punkte", new HomePointSorter(), ps,
					"homep");
			createHtmlTable(teams, "Heim: Verlustpunkte",
					new HomeLossPointSorter(), ps, "homevp");
			ps.println("</div>");

			ps.println("<div id=\"out\">");
			createHtmlTable(teams, "Ausw&auml;rts: Punkte",
					new OutwardPointSorter(), ps, "outp");
			createHtmlTable(teams, "Ausw&auml;rts: Verlustpunkte",
					new OutwardLossPointSorter(), ps, "outvp");
			ps.println("</div>");

			ps.println("</body></html>");
		} catch (JDOMException e) {
			LOG.log(Level.SEVERE, "Error while parsing the HTML", e);
			ps.println("<html><body><p>An error occurred: </p><pre>");
			e.printStackTrace(ps);
			ps.println("</pre></body></html>");
		}

	}

	private void createHtmlTable(ArrayList<Team> teams, String title,
			InfoSorter sorter, PrintStream os, String divId) {

		Collections.sort(teams, sorter);

		os.print("<div id=\"");
		os.print(divId);
		os.println("\">");
		os.println("<h1>" + title + "</h1>");
		os.print("<table>");
		os.print("<tr>");
		os.print("<th>Rang</th>");
		os.print("<th>Team</th>");
		os.print("<th>S</th>");
		os.print("<th>U</th>");
		os.print("<th>N</th>");
		os.print("<th>T+</th>");
		os.print("<th>T-</th>");
		os.print("<th>P</th>");
		os.print("<th>VP</th>");
		os.print("<th>T+/-</th>");
		os.println("</tr>");
		// iterate and show

		int rang = 1;
		boolean odd = true;
		for (Team t : teams) {
			String className = t.getName().toLowerCase();

			// only take letters, everything else is "illegal"
			int i = 0;
			StringBuilder cn = new StringBuilder(className);
			while (i < cn.length()) {
				if (cn.charAt(i) >= 'a' && cn.charAt(i) <= 'z') {
					// hold it
					i++;
				} else {
					cn.deleteCharAt(i);
				}
			}
			os.print("<tr id=\"");
			os.print(cn.toString());
			os.print("\" class=\"");
			os.print(odd ? "odd" : "even");
			odd = !odd;
			os.print("\">");
			wrap(os, rang++, "rang");
			wrap(os, t.getName(), "name");
			wrap(os, sorter.getWins(t), "win");
			wrap(os, sorter.getDraws(t), "draw");
			wrap(os, sorter.getLoss(t), "loss");
			wrap(os, sorter.getMade(t), "made");
			wrap(os, sorter.getGotten(t), "got");
			wrap(os, sorter.getPoints(t), "point");
			wrap(os, sorter.getLossPoints(t), "minpoint");
			wrap(os, sorter.getDiff(t), "diff");
			os.println("</tr>");
		}

		os.println("</table></div>");
	}

	private void wrap(PrintStream os, Object object, String divClass) {
		os.print("<td class=\"");
		os.print(divClass);
		os.print("\">");
		os.print(object);
		os.print("</td>");
	}
}
